﻿using Common.Communication;
using Common.Device.DeviceDb;
using Common.Device.Enums;
using Common.Device.Interfaces;
using Common.Tool.DataTools;
using EnumsNET;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Org.BouncyCastle.Crypto.Engines.SM2Engine;

namespace GeChaoJi.CheShenYu
{
    internal class N110CSerialPort : SerialPortBase, IGeChaoJi
    {
        public string Name { get; set; }
        byte Addr;
        public N110CSerialPort(UseDevice device) : base(device.port, Convert.ToInt32(device.parameter), timeout: 1500)
        {
            Name = device.name;
            Addr = Convert.ToByte(device.addr);
        }

        public Result<bool> GetCMD_NULL(int channel = 1)
        {
            lock (this)
            {
                var result = new Result<bool>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                var read = new Result<byte[]>();
                AppendInfo(Name, $"空命令");
                var command = CmdReadCMD_NULLValue();
                write = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_NULLOk;
                
                if (!write.IsSucceed || !write.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(write.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "空命令通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=0)
                {
                    result.IsSucceed = false;
                    result.Err = "空命令通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value=true;
                return result.EndTime();
            }
        }

        public Result<int> GetCMD_R_INIT(int channel = 1)
        {
            lock (this)
            {
                var result = new Result<int>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                AppendInfo(Name, $"读初始化状态");
                var command = CmdReadCMD_R_INITValue();
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_R_INITOk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=1)
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value = read.Value[5];
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<int> GetCMD_T_BEGIN(int channel = 1)
        {
            lock (this)
            {
                var result = new Result<int>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                int[] getint = new int[9];
                AppendInfo(Name, $"开始测试模式");
                var command = CmdReadCMD_T_BEGINValue();
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_T_BEGINOk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "开始测试模式通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=1)
                {
                    result.IsSucceed = false;
                    result.Err = "读参数通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value = read.Value[5];
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<int[]> GetCMD_R_PARA(int channel = 1)
        {
            lock (this)
            {
                var result = new Result<int[]>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                int[] getint = new int[9];
                AppendInfo(Name, $"读参数");
                var command = CmdReadCMD_R_PARAValue();
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_R_PARAOk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读参数通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=9)
                {
                    result.IsSucceed = false;
                    result.Err = "读参数通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                bytes1[0] = read.Value[5];
                bytes1[1] = read.Value[6];
                getint[0] = (bytes1[1] << 8) | (bytes1[0]);
                for (int i = 0; i<temp-2; i++)
                {
                    getint[i] = read.Value[7+i];
                }
                result.Value = getint;
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<int[]> GetCMD_R_INPUT(GeChaoJiEnum.DianPinMode DianJiMode, int channel = 1)
        {
            lock (this)
            {
                var result = new Result<int[]>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                int[] getint = new int[16];
                AppendInfo(Name, $"读端口输入");
                var command = CmdReadCMD_R_INPUTValue(DianJiMode);
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_R_INPUTOk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读端口输入通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=2)
                {
                    result.IsSucceed = false;
                    result.Err = "读端口输入通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                int index = 0;
                for (int i=0;i<2;i++)
                {
                    byte getone = read.Value[5+i];
                    for (int num = 7; num >= 0; num--)
                    {
                        getint[index] = (getone >> num) & 1; // 提取第 i 位
                        index++;
                    }
                }
                //result.Value = getint;
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<int[]> GetCMD_T_COMMPORT(int channel = 1)
        {
            lock (this)
            {
                var result = new Result<int[]>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                int[] getint = new int[8];
                AppendInfo(Name, $"读初始化状态");
                var command = CmdReadCMD_T_COMMPORTValue();
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_T_COMMPORTOk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=2)
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                int index = 0;

                byte getone = read.Value[5];
                for (int num = 7; num >= 0; num--)
                {
                    getint[index] = (getone >> num) & 1; // 提取第 i 位
                    index++;
                }
                //result.Value = getint;
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<int> GetCMD_T_LIFTMOTOR(GeChaoJiEnum.DianJiMode DianJiMode, int channel = 1)
        {
            lock (this)
            {
                var result = new Result<int>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                AppendInfo(Name, $"读初始化状态");
                var command = CmdReadCMD_T_LIFTMOTORValue(DianJiMode);
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_T_LIFTMOTOROk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=1)
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value = read.Value[5];
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<double> GetCMD_T_WALKMOTOR(GeChaoJiEnum.DianJiMode DianJiMode, int channel = 1)
        {
            lock (this)
            {
                var result = new Result<double>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                AppendInfo(Name, $"读初始化状态");
                var command = CmdReadCMD_T_WALKMOTORValue(DianJiMode);
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_T_WALKMOTOROk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=4)
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value = read.Value[5];
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<double> GetCMD_T_MOWMOTOR(GeChaoJiEnum.DianJiMode DianJiMode, int channel = 1)
        {
            lock (this)
            {
                var result = new Result<double>();
                var read = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] bytes1 = new byte[2];
                AppendInfo(Name, $"读初始化状态");
                var command = CmdReadCMD_T_MOWMOTORValue(DianJiMode);
                read = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_T_MOWMOTOROk;
                if (!read.IsSucceed || !read.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(read.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=2)
                {
                    result.IsSucceed = false;
                    result.Err = "读初始化状态通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value = read.Value[5];
                //result.Value = ((read.Value[6] << 24) + (read.Value[5] << 16) + (read.Value[4] << 8) + read.Value[3]);
                return result.EndTime();
            }
        }

        public Result<bool> GetCMD_T_END(int channel = 1)
        {
            lock (this)
            {
                var result = new Result<bool>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                var read = new Result<byte[]>();
                AppendInfo(Name, $"CMD_T_END");
                var command = CmdReadCMD_T_ENDValue();
                write = WriteThenRead(command, wait: 100);
                var want = CmdSetdCMD_T_ENDOk;

                if (!write.IsSucceed || !write.Value.Take(want.Length).SequenceEqual(want)||!ByteHelper.CheckCRC16(write.Value))
                {
                    result.IsSucceed = false;
                    result.Err = "CMD_T_END通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                bytes[0] = read.Value[3];
                bytes[1] = read.Value[4];
                var temp = (bytes[1] << 8) | (bytes[0]);
                if (read.Value.Length!=temp+6||temp!=0)
                {
                    result.IsSucceed = false;
                    result.Err = "CMD_T_END通信失败长度协议错误";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value=true;
                return result.EndTime();
            }
        }
        byte[] CmdReadCMD_NULLValue()
        {
            byte[] order = new byte[] { 0x55, 0xAA, 0x00, 0x00, 0x00 };
            return ByteHelper.GetCRC16(order);
        }

        byte[] CmdSetdCMD_NULLOk => new byte[3] { 0x55, 0xAA, 0x00 };
        byte[] CmdReadCMD_R_INITValue()
        {
            byte[] order = new byte[] { 0x55, 0xAA, 0x01, 0x00, 0x00};
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_R_INITOk => new byte[3] { 0x55, 0xAA, 0x01 };
        byte[] CmdReadCMD_T_BEGINValue()
        {
            byte[] order = new byte[] { 0x55, 0xAA, 0x02, 0x00, 0x00 };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_T_BEGINOk => new byte[3] { 0x55, 0xAA, 0x02 };
        byte[] CmdReadCMD_R_PARAValue()
        {
            byte[] order = new byte[] { 0x55, 0xAA, 0x03, 0x00, 0x00 };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_R_PARAOk => new byte[3] { 0x55, 0xAA, 0x03 };
        byte[] CmdReadCMD_R_INPUTValue(GeChaoJiEnum.DianPinMode mode)
        {
            int index = 0;
            switch (mode)
            {
                case GeChaoJiEnum.DianPinMode.高电平: index = 1; break;
                case GeChaoJiEnum.DianPinMode.低电平: index = 0; break;
                default:
                    break;
            }
            byte[] order = new byte[] { 0x55, 0xAA, 0x04, 0x01, 0x00, Convert.ToByte(index) };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_R_INPUTOk => new byte[3] { 0x55, 0xAA, 0x04 };
        byte[] CmdReadCMD_T_COMMPORTValue()
        {
            byte[] order = new byte[] { 0x55, 0xAA, 0x05, 0x00, 0x00 };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_T_COMMPORTOk => new byte[3] { 0x55, 0xAA, 0x05 };
        byte[] CmdReadCMD_T_LIFTMOTORValue(GeChaoJiEnum.DianJiMode DianJiMode)
        {
            int index = 0;
            switch (DianJiMode)
            {
                case GeChaoJiEnum.DianJiMode.停止: index = 0; break;
                case GeChaoJiEnum.DianJiMode.正转: index = 1; break;
                case GeChaoJiEnum.DianJiMode.反转: index = 2; break;
                default:
                    break;
            }
            byte[] order = new byte[] { 0x55, 0xAA, 0x06, 0x01, 0x00, Convert.ToByte(index) };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_T_LIFTMOTOROk => new byte[3] { 0x55, 0xAA, 0x06 };
        byte[] CmdReadCMD_T_WALKMOTORValue(GeChaoJiEnum.DianJiMode DianJiMode)
        {
            int index = 0;
            switch (DianJiMode)
            {
                case GeChaoJiEnum.DianJiMode.停止: index = 0; break;
                case GeChaoJiEnum.DianJiMode.正转: index = 1; break;
                case GeChaoJiEnum.DianJiMode.反转: index = 2; break;
                default:
                    break;
            }
            byte[] order = new byte[] { 0x55, 0xAA, 0x07, 0x01, 0x00, Convert.ToByte(index) };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_T_WALKMOTOROk => new byte[3] { 0x55, 0xAA, 0x07 };
        byte[] CmdReadCMD_T_MOWMOTORValue(GeChaoJiEnum.DianJiMode DianJiMode)
        {
            int index = 0;
            switch (DianJiMode)
            {
                case GeChaoJiEnum.DianJiMode.停止: index = 0; break;
                case GeChaoJiEnum.DianJiMode.正转: index = 1; break;
                case GeChaoJiEnum.DianJiMode.反转: index = 2; break;
                default:
                    break;
            }
            byte[] order = new byte[] { 0x55, 0xAA, 0x08, 0x01, 0x00, Convert.ToByte(index) };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_T_MOWMOTOROk => new byte[3] { 0x55, 0xAA, 0x08 };
        byte[] CmdReadCMD_T_ENDValue()
        {
            byte[] order = new byte[] { 0x55, 0xAA, 0x09, 0x00, 0x00 };
            return ByteHelper.GetCRC16(order);
        }
        byte[] CmdSetdCMD_T_ENDOk => new byte[3] { 0x55, 0xAA, 0x09 };

    }
}
